import hashlib
import random
import requests
import json
import time
import hmac
import base64
import xml.etree.ElementTree as ET
from urllib.parse import quote
from config.settings import load_config
from PyQt6.QtCore import QThread, pyqtSignal
import pytesseract
from PIL import ImageGrab

class Translator:
    def __init__(self, language="英语"):
        self.language = language
        self.config = load_config()
        self.translation_cache = {}  # 添加翻译缓存
        self.cache_size = 1000  # 缓存大小限制
        
    def translate(self, text):
        """
        翻译文本
        
        Args:
            text: 要翻译的文本
            
        Returns:
            str: 翻译后的文本
        """
        # 检查缓存中是否存在翻译
        if text in self.translation_cache:
            return self.translation_cache[text]
            
        selected_api = self.config.get('selected_api', 'deepseek')
        
        if selected_api == 'deepseek':
            result = self._translate_with_deepseek(text)
        elif selected_api == 'baidu':
            result = self._translate_with_baidu(text)
        elif selected_api == 'tencent':
            result = self._translate_with_tencent(text)
        elif selected_api == 'aliyun':
            result = self._translate_with_aliyun(text)
        else:
            result = "不支持的翻译API"
            
        # 将翻译结果存入缓存
        if len(self.translation_cache) >= self.cache_size:
            # 如果缓存已满，删除最早的条目
            self.translation_cache.pop(next(iter(self.translation_cache)))
        self.translation_cache[text] = result
        
        return result
            
    def _translate_with_deepseek(self, text):
        """使用DeepSeek API翻译"""
        config = self.config['deepseek']
        api_key = config.get('api_key')
        
        if not api_key:
            return "请先配置DeepSeek API密钥"
            
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }
        
        # 获取用户配置的提示词
        custom_prompt = config.get('prompt', '你是一个专业的翻译助手，请将以下文本翻译成中文：')
        
        # 如果文本太长，进行分段处理
        max_length = 1000  # 每段最大长度
        if len(text) > max_length:
            # 按句子分割文本
            sentences = text.split('.')
            segments = []
            current_segment = ""
            
            for sentence in sentences:
                if len(current_segment) + len(sentence) < max_length:
                    current_segment += sentence + "."
                else:
                    if current_segment:
                        segments.append(current_segment)
                    current_segment = sentence + "."
            
            if current_segment:
                segments.append(current_segment)
                
            # 翻译每个段落
            translated_segments = []
            for segment in segments:
                result = self._make_deepseek_request(segment.strip(), custom_prompt, headers, config['api_url'])
                if result.startswith("翻译失败") or result.startswith("翻译出错") or result.startswith("翻译超时"):
                    return result
                translated_segments.append(result)
                    
            return " ".join(translated_segments)
        else:
            # 短文本直接翻译
            return self._make_deepseek_request(text, custom_prompt, headers, config['api_url'])
            
    def _make_deepseek_request(self, text, prompt, headers, api_url, max_retries=3):
        """发送DeepSeek API请求，带重试机制"""
        data = {
            "model": "deepseek-chat",
            "messages": [
                {
                    "role": "system",
                    "content": prompt
                },
                {
                    "role": "user",
                    "content": text
                }
            ],
            "temperature": 0.3,  # 降低随机性
            "max_tokens": 1000  # 限制输出长度
        }
        
        for attempt in range(max_retries):
            try:
                # 根据重试次数增加超时时间
                timeout = 15 + (attempt * 5)  # 第一次15秒，第二次20秒，第三次25秒
                response = requests.post(
                    api_url,
                    headers=headers,
                    json=data,
                    timeout=timeout
                )
                
                if response.status_code == 200:
                    result = response.json()
                    return result['choices'][0]['message']['content']
                else:
                    if attempt == max_retries - 1:  # 最后一次尝试
                        return f"翻译失败: {response.text}"
                    time.sleep(1)  # 等待1秒后重试
            except requests.Timeout:
                if attempt == max_retries - 1:  # 最后一次尝试
                    return "翻译超时，请重试"
                time.sleep(1)  # 等待1秒后重试
            except Exception as e:
                if attempt == max_retries - 1:  # 最后一次尝试
                    return f"翻译出错: {str(e)}"
                time.sleep(1)  # 等待1秒后重试
            
    def _translate_with_baidu(self, text):
        """使用百度翻译API翻译"""
        config = self.config['baidu']
        app_id = config.get('app_id')
        app_key = config.get('app_key')
        
        if not app_id or not app_key:
            return "请先配置百度翻译APP ID和密钥"
            
        # 预处理文本
        text = ' '.join(text.split())
        
        salt = str(random.randint(32768, 65536))
        sign = hashlib.md5((app_id + text + salt + app_key).encode()).hexdigest()
        
        # 根据当前选择的语言设置源语言
        if self.language == "英语":
            from_lang = "en"
        elif self.language == "日语":
            from_lang = "jp"
        elif self.language == "韩语":
            from_lang = "kor"
        else:
            from_lang = "auto"
        
        params = {
            'q': text,
            'from': from_lang,
            'to': 'zh',
            'appid': app_id,
            'salt': salt,
            'sign': sign
        }
        
        try:
            response = requests.get(config['api_url'], params=params)
            
            if response.status_code == 200:
                result = response.json()
                if 'trans_result' in result:
                    # 合并所有翻译结果
                    return ' '.join(item['dst'] for item in result['trans_result'])
                else:
                    return f"翻译失败: {result.get('error_msg', '未知错误')}"
            else:
                return f"翻译失败: {response.text}"
        except Exception as e:
            return f"翻译出错: {str(e)}"

    def _translate_with_tencent(self, text):
        """使用腾讯翻译API翻译"""
        config = self.config['tencent']
        secret_id = config.get('secret_id')
        secret_key = config.get('secret_key')
        
        if not secret_id or not secret_key:
            return "请先配置腾讯翻译SecretId和SecretKey"
            
        # 预处理文本
        text = ' '.join(text.split())
        
        # 根据当前选择的语言设置源语言
        if self.language == "英语":
            from_lang = "en"
        elif self.language == "日语":
            from_lang = "ja"
        elif self.language == "韩语":
            from_lang = "ko"
        else:
            from_lang = "auto"
        
        # 生成签名
        timestamp = int(time.time())
        date = time.strftime("%Y-%m-%d", time.gmtime(timestamp))
        endpoint = "tmt.tencentcloudapi.com"
        service = "tmt"
        region = "ap-guangzhou"
        action = "TextTranslate"
        version = "2018-03-21"
        
        # 构建请求参数
        payload = {
            "SourceText": text,
            "Source": from_lang,
            "Target": "zh",
            "ProjectId": 0
        }
        
        # 生成签名
        http_request_method = "POST"
        canonical_uri = "/"
        canonical_querystring = ""
        signed_headers = "content-type;host"
        payload_str = json.dumps(payload)
        hashed_request_payload = hashlib.sha256(payload_str.encode("utf-8")).hexdigest()
        
        canonical_headers = f"content-type:application/json\nhost:{endpoint}\n"
        string_to_sign = f"TC3-HMAC-SHA256\n{timestamp}\n{date}/{service}/tc3_request\n" + \
                        hashlib.sha256((http_request_method + "\n" + canonical_uri + "\n" + canonical_querystring + "\n" + 
                                      canonical_headers + "\n" + signed_headers + "\n" + hashed_request_payload).encode("utf-8")).hexdigest()
        
        secret_date = hmac.new(("TC3" + secret_key).encode("utf-8"), date.encode("utf-8"), hashlib.sha256).digest()
        secret_service = hmac.new(secret_date, service.encode("utf-8"), hashlib.sha256).digest()
        secret_signing = hmac.new(secret_service, "tc3_request".encode("utf-8"), hashlib.sha256).digest()
        signature = hmac.new(secret_signing, string_to_sign.encode("utf-8"), hashlib.sha256).hexdigest()
        
        authorization = f"TC3-HMAC-SHA256 Credential={secret_id}/{date}/{service}/tc3_request, SignedHeaders={signed_headers}, Signature={signature}"
        
        headers = {
            "Authorization": authorization,
            "Content-Type": "application/json",
            "Host": endpoint,
            "X-TC-Action": action,
            "X-TC-Version": version,
            "X-TC-Timestamp": str(timestamp),
            "X-TC-Region": region
        }
        
        try:
            response = requests.post(
                f"https://{endpoint}",
                headers=headers,
                data=payload_str
            )
            
            if response.status_code == 200:
                result = response.json()
                if 'Response' in result and 'TargetText' in result['Response']:
                    return result['Response']['TargetText']
                else:
                    return f"翻译失败: {result.get('Response', {}).get('Error', {}).get('Message', '未知错误')}"
            else:
                return f"翻译失败: {response.text}"
        except Exception as e:
            return f"翻译出错: {str(e)}"
            
    def _translate_with_aliyun(self, text):
        """使用阿里翻译API翻译"""
        config = self.config['aliyun']
        access_key = config.get('access_key')
        access_secret = config.get('access_secret')
        
        if not access_key or not access_secret:
            return "请先配置阿里翻译AccessKey和AccessSecret"
            
        # 预处理文本
        text = ' '.join(text.split())
        
        # 根据当前选择的语言设置源语言
        from_lang = "en" if self.language == "英语" else "ja"
        
        # 构建请求参数
        params = {
            "Action": "TranslateGeneral",
            "Version": "2018-10-12",
            "FormatType": "text",
            "SourceLanguage": from_lang,
            "TargetLanguage": "zh",
            "SourceText": text,
            "Scene": "general",
            "AccessKeyId": access_key,
            "SignatureMethod": "HMAC-SHA1",
            "SignatureVersion": "1.0",
            "SignatureNonce": str(random.randint(100000, 999999)),
            "Timestamp": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
        }
        
        # 构建规范化的参数字符串
        canonicalized_query_string = "&".join([f"{quote(k, safe='')}={quote(str(v), safe='')}" for k, v in sorted(params.items())])
        
        # 构建签名字符串
        string_to_sign = f"GET&%2F&{quote(canonicalized_query_string)}"
        
        # 计算签名
        signature = base64.b64encode(
            hmac.new(
                (access_secret + "&").encode('utf-8'),
                string_to_sign.encode('utf-8'),
                hashlib.sha1
            ).digest()
        ).decode('utf-8')
        
        # 添加签名到参数中
        params["Signature"] = signature
        
        try:
            response = requests.get(
                config['api_url'],
                params=params
            )
            
            if response.status_code == 200:
                try:
                    # 尝试解析XML响应
                    root = ET.fromstring(response.text)
                    
                    # 检查是否有错误
                    error = root.find('Error')
                    if error is not None:
                        error_code = error.find('Code').text
                        error_message = error.find('Message').text
                        return f"翻译失败: {error_code} - {error_message}"
                    
                    # 解析翻译结果
                    translated = root.find('.//Translated')
                    if translated is not None:
                        return translated.text
                    else:
                        return "翻译失败: 未找到翻译结果"
                except ET.ParseError:
                    # 如果不是XML，尝试解析JSON
                    try:
                        result = response.json()
                        if 'Data' in result and 'Translated' in result['Data']:
                            return result['Data']['Translated']
                        else:
                            return f"翻译失败: {result.get('Message', '未知错误')}"
                    except json.JSONDecodeError:
                        return f"翻译失败: 无法解析响应 - {response.text}"
            else:
                return f"翻译失败: {response.text}"
        except Exception as e:
            return f"翻译出错: {str(e)}"

class TranslationWorker(QThread):
    translation_ready = pyqtSignal(str, str)  # 修改信号，发送原文和译文
    error = pyqtSignal(str)
    
    def __init__(self, region, language='eng', translate_btn=None, resize_btn=None):
        super().__init__()
        # 将QRect转换为坐标元组 (left, top, right, bottom)
        self.region = (region.x(), region.y(), region.x() + region.width(), region.y() + region.height())
        # 将语言代码转换为对应的语言名称
        self.language = "英语" if language == "eng" else "日语"
        self.running = True
        self.translator = Translator(language=self.language)
        self.translate_btn = translate_btn
        self.resize_btn = resize_btn
        
    def run(self):
        try:
            while self.running:
                # 临时隐藏按钮
                if self.translate_btn:
                    self.translate_btn.hide()
                if self.resize_btn:
                    self.resize_btn.hide()
                    
                # 截取屏幕区域
                screenshot = ImageGrab.grab(bbox=self.region)
                # OCR识别
                text = pytesseract.image_to_string(screenshot, lang="eng" if self.language == "英语" else "jpn")
                
                # 重新显示按钮
                if self.translate_btn:
                    self.translate_btn.show()
                if self.resize_btn:
                    self.resize_btn.show()
                    
                if text.strip():
                    print("\n=== OCR识别结果 ===")
                    print(f"识别文本: {text.strip()}")
                    # 翻译文本
                    translated_text = self.translator.translate(text.strip())
                    # 发送原文和译文
                    self.translation_ready.emit(text.strip(), translated_text)
                time.sleep(1)  # 每秒检查一次
        except Exception as e:
            # 确保在发生异常时也显示按钮
            if self.translate_btn:
                self.translate_btn.show()
            if self.resize_btn:
                self.resize_btn.show()
            self.error.emit(str(e))
            
    def stop(self):
        self.running = False 